#include "GpioPort.h"

GpioPort::GpioPort()
{
    available = init();
}

GpioPort::~GpioPort()
{
    unInit();
}

bool GpioPort::init()
{
    /* initializing Susi library */
    mutex.lock();
    bool susiInitStatus = SusiDllInit();
    if(!susiInitStatus) {
        mutex.unlock();
        return false;
    }

    /* looking for Susi driver */
    int susiCoreStatus = SusiCoreAvailable();
    mutex.unlock();

    if((susiCoreStatus == 0) || (susiCoreStatus == -1))
        return false;

    return true;
}

void GpioPort::unInit()
{
    mutex.lock();
    SusiDllUnInit();
    mutex.unlock();
}

int GpioPort::setDirection(int pin, bool dir)
{
    DWORD retDirMask;
    BYTE pinByte = static_cast<BYTE>(pin);
    BYTE dirByte = static_cast<BYTE>(dir);

    mutex.lock();
    int setPinStatus = SusiIOSetDirection(pinByte, dirByte, &retDirMask);
    mutex.unlock();

    if(!setPinStatus)
        return 1;

    return 0;
}

int GpioPort::setDirectionMulti(int pinMask, int dirMask)
{
    DWORD pinMaskDword = static_cast<DWORD>(pinMask);
    DWORD dirMaskDword = static_cast<DWORD>(dirMask);
    DWORD retDirMask = dirMaskDword;

    mutex.lock();
    int setPinStatus = SusiIOSetDirectionMulti(pinMaskDword, &retDirMask);
    mutex.unlock();

    if(!setPinStatus || (retDirMask != dirMaskDword))
        return 1;

    return 0;
}

int GpioPort::setState(int pin, bool state)
{
    BYTE pinByte = static_cast<BYTE>(pin);
    BOOL stateBool = static_cast<BOOL>(state);
    BOOL retPinState;

    mutex.lock();
    int setPinStatus = SusiIOWriteEx(pinByte, stateBool);
    SusiIOReadEx(pinByte, &retPinState);
    mutex.unlock();

    if(!setPinStatus || (stateBool != retPinState))
        return 1;

    return 0;
}

int GpioPort::setStateMulti(int pinMask, int stateMask)
{
    DWORD pinMaskDword = static_cast<DWORD>(pinMask);
    DWORD stateMaskDword = static_cast<DWORD>(stateMask);

    mutex.lock();
    int setPinStatus = SusiIOWriteMultiEx(pinMaskDword, stateMaskDword);
    mutex.unlock();

    if(!setPinStatus)
        return 1;

    return 0;
}

int GpioPort::getState(int pin, bool *state)
{
    BYTE pinByte = static_cast<BYTE>(pin);
    BOOL pinState;

    mutex.lock();
    int getPinStatus = SusiIOReadEx(pinByte, &pinState);
    mutex.unlock();

    *state = static_cast<bool>(pinState);
    if(!getPinStatus)
        return 1;
    /*{
        // !!!!! DEBUG !!!!!
        *state = true;
        return 0;
        }*/

    return 0;
}

int GpioPort::getStateMulti(int pinMask, int *stateMask)
{
    DWORD pinMaskDword = static_cast<DWORD>(pinMask);
    DWORD pinStateMask;

    mutex.lock();
    int getPinStatus = SusiIOReadMultiEx(pinMaskDword, &pinStateMask);
    mutex.unlock();

    *stateMask = static_cast<int>(pinStateMask);
    if(!getPinStatus)
        return 1;

    return 0;
}

bool GpioPort::isAvailable()
{
    return available;
}
